package com.isoftstone.securityframework.device.local;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.ibatis.session.SqlSession;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.isoftstone.securityframework.api.AccountManager.AuthStatus;
import com.isoftstone.securityframework.api.domain.Account;
import com.isoftstone.securityframework.api.domain.Permission;
import com.isoftstone.securityframework.api.util.AuthUtil;
import com.isoftstone.securityframework.auth.realm.SubjectRealm;
import com.isoftstone.securityframework.device.domain.Device;
import com.isoftstone.securityframework.device.domain.DeviceExt;
import com.isoftstone.securityframework.device.DeviceGroupManager;
import com.isoftstone.securityframework.device.DeviceManager;
import com.isoftstone.securityframework.device.domain.DeviceGroup;
import com.isoftstone.securityframework.device.exception.DeviceException;

@Service
@Transactional
public class DeviceManagerLocalImpl implements DeviceManager,SubjectRealm{

	@Resource
	private SqlSession session = null;
	
	@Resource
	private DeviceGroupManager groupManager = null;

	@Override
	public Device register(Device device, 
			Serializable[] groupIds, Serializable[] permissionIds)
			throws DeviceException {
		if(device.getDeviceFlag()==null || "".equals(device.getDeviceFlag())){
			throw new DeviceException("Deviceflag must not be null");
		}
		session.insert("com.isoftstone.securityframework.DeviceMapper.insertDevice",device);

		if(device.getDeivceExts()!=null && device.getDeivceExts().size()>0){
			for (DeviceExt e : device.getDeivceExts()) {
				e.setDeviceId(device.getId());
				e.setDeviceFlag(device.getDeviceFlag());
				session.insert("com.isoftstone.securityframework.DeviceMapper.insertDeviceExt",device);
			}
		}
		
		if(groupIds!=null && groupIds.length>0){
			groupManager.relDeviceGroup(device, groupIds);
		}
		if(device.getGroups()!=null && device.getGroups().size()>0){
			groupManager.relDeviceGroup(device, device.getGroups().toArray(new DeviceGroup[]{}));
		}

		if(permissionIds!=null && permissionIds.length>0){
			this.relDevicePermission(device, permissionIds);
		}
		if(device.getPermissions()!=null && device.getPermissions().size()>0){
			this.relDevicePermission(device, device.getPermissions().toArray(new Permission[]{}));
		}
		return device;
	}
	
	@Override
	public Device register(Device device)throws DeviceException {
		return this.register(device, null, null);
	}

	
	@Override
	public Device register(Device device,AuthStatus status)throws DeviceException {
		device.setStatus(status.getIndex());
		return this.register(device, null, null);
	}

	@Override
	public Device registerWithPermissions(Device device,
			Permission[] permissions) throws DeviceException {
		List<Serializable> list = new ArrayList<Serializable>();
		for (Permission p: permissions) {
			list.add(p.getId());
		}
		return this.register(device,null,list.toArray(new Serializable[]{}));
	}

	@Override
	public Device registerWithPermissions(Device device,
			Serializable[] permissionIds) throws DeviceException {
		return this.register(device,null,permissionIds);
	}

	@Override
	public Device registerWithGroups(Device device, DeviceGroup[] groups) throws DeviceException {
		List<Serializable> list = new ArrayList<Serializable>();
		for (DeviceGroup g: groups) {
			list.add(g.getId());
		}
		return this.register(device,list.toArray(new Serializable[]{}),null);
	}

	@Override
	public Device registerWithGroups(Device device,
			Serializable[] groupIds) throws DeviceException {
		return this.register(device,groupIds,null);
	}

	@Override
	public Device get(Integer id) {
		return (Device) session.selectOne("com.isoftstone.securityframework.DeviceMapper.getById",id);
	}

	@Override
	public Device get(String deviceFlag) {
		return (Device) session.selectOne("com.isoftstone.securityframework.DeviceMapper.getByFlag",deviceFlag);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Device> list() {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("paltformId", AuthUtil.getPlatformId());
		return session.selectList("com.isoftstone.securityframework.DeviceMapper.list",params);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Device> list(Map<String, Object> params) {
		if(params==null || params.size()<=0)
			return this.list();

		if(!params.containsKey("platformId")){
			params.remove("platformId");
			params.put("platformId", AuthUtil.getPlatformId());
		}
		return session.selectList("com.isoftstone.securityframework.DeviceMapper.list",params);
	}

	@Override
	public void relAccountDevice(Account account, Device[] Devices) {

		List<Integer> list = new ArrayList<Integer>();
		for (Device t : Devices) {
			list.add(t.getId());
		}
		this.relAccountDevice(account.getId(), list.toArray(new Serializable[]{}));
	}
	

	public void relAccountDevice(Account account,Serializable[] DeviceIds){
		this.relAccountDevice(account.getId(), DeviceIds);
	}
	public void relAccountDevice(Serializable accountId,Serializable[] DeviceIds){

		if(DeviceIds==null){
			throw new RuntimeException("accountId can not be null!");
		}
		Map<String,Integer> params = new HashMap<String,Integer>();
		for (Serializable id : DeviceIds) {
			params.put("DeviceId",(Integer) id);
			params.put("accountId", (Integer)accountId);
			session.insert("com.isoftstone.securityframework.DeviceMapper.relAccountDevices",params);
			params.clear();
		}
		
	}

	@Override
	public void unrelAccountDevice(Account account, Device[] Devices) {
		List<Integer> list = new ArrayList<Integer>();
		for (Device t : Devices) {
			list.add(t.getId());
		}
		this.unrelAccountDevice(account.getId(), list.toArray(new Serializable[]{}));
	}

	@Override
	public void unrelAccountDevice(Account account, Serializable[] DeviceIds) {
		this.unrelAccountDevice(account.getId(), DeviceIds);
		
	}
	@Override
	public void unrelAccountDevice(Serializable accountId,Serializable[] DeviceIds){
		if(DeviceIds==null){
			throw new RuntimeException("accountId can not be null!");
		}
		Map<String, Object> params = new HashMap<String, Object>();
		for (Serializable DeviceId : DeviceIds) {
			params.put("accountId", accountId);
			params.put("DeviceId", DeviceId);
			session.delete("com.isoftstone.securityframework.DeviceMapper.unrelAccountDevices",params);
			params.clear();
		}
	
	}

	@Override
	public void relDevicePermission(Device device, Permission[] permissions) {

		List<Integer> list = new ArrayList<Integer>();
		for (Permission p : permissions) {
			list.add(p.getId());
		}
		this.relDevicePermission(device.getId(), list.toArray(new Serializable[]{}));		
	}

	@Override
	public void relDevicePermission(Device termianl,
			Serializable[] permissionIds) {
		this.relDevicePermission(termianl.getId(), permissionIds);	
		
	}

	@Override
	public void relDevicePermission(Serializable deviceId,
			Serializable[] permissionIds) {
		if(deviceId==null){
			throw new RuntimeException("deviceId can not be null!");
		}
		Map<String,String> params = new HashMap<String,String>();
		for (Serializable id : permissionIds) {
			params.put("deviceId", (String) deviceId);
			params.put("permId",(String)id);
			session.insert("com.isoftstone.securityframework.DeviceMapper.relDevicePermission",params);
			params.clear();
		}					
	}

	@Override
	public void unrelDevicePermission(Device device, Permission[] permissions) {

		List<Integer> list = new ArrayList<Integer>();
		for (Permission p : permissions) {
			list.add(p.getId());
		}
		this.unrelDevicePermission(device.getId(), list.toArray(new Serializable[]{}));		
	}

	@Override
	public void unrelDevicePermission(Device termianl,
			Serializable[] permissionIds) {
		this.unrelDevicePermission(termianl.getId(), permissionIds);	
		
	}

	@Override
	public void unrelDevicePermission(Serializable deviceId,
			Serializable[] permissionIds) {
		if(deviceId==null){
			throw new RuntimeException("deviceId can not be null!");
		}
		Map<String,String> params = new HashMap<String,String>();
		for (Serializable id : permissionIds) {
			params.put("deviceId", (String) deviceId);
			params.put("permId",(String)id);
			session.delete("com.isoftstone.securityframework.DeviceMapper.unrelDevicePermission",params);
			params.clear();
		}				
	}

	@Override
	public Subject getSubject(String principal) {
		return (Subject) this.get(principal);
	}

	@Override
	public Subject recordLogin(Subject subject) {
		return null;
	}


}
